﻿#ifndef JTHREADPOOL_GLOBAL_H
#define JTHREADPOOL_GLOBAL_H

// - JTHREADPOOL_VERSION is (major << 16) + (minor << 8) + patch.

#define JTHREADPOOL_VERSION       0x010000
#define JTHREADPOOL_VERSION_STR   "1.0.0"

#ifdef _MSC_VER

#if defined(JTHREADPOOL_MAKE)
#define JTHREADPOOL_EXPORT __declspec(dllexport)
#else
#define JTHREADPOOL_EXPORT __declspec(dllimport)

#endif  // defined(JTHREADPOOL_MAKE)

#endif  // _MSC_VER

#ifndef JTHREADPOOL_EXPORT
#define JTHREADPOOL_EXPORT
#endif

#if defined(_MSC_VER)

#ifndef JTHREADPOOL_MAKE

#if defined(_DEBUG) || defined(DEBUG)
#pragma comment(lib, "jthreadpoold.lib")
#else
#pragma comment(lib, "jthreadpool.lib")
#endif  // defined(_DEBUG) || defined(DEBUG)

#endif  // !JTHREADPOOL_MAKE

#endif

#include <utility>

//
#ifndef J_DECLARE_OBSERVER
#define J_DECLARE_OBSERVER(_class_) \
    public: \
        void setObserver(_class_ ## Observer *add, _class_ ## Observer *remove = 0); \
    private:
#endif

namespace JConcurrent {
    typedef void *HANDLE;
}

#ifndef J_DISABLE_COPY
#define J_DISABLE_COPY(Class) \
    Class(const Class &); \
    Class &operator=(const Class &);
#endif

// Avoid "unused parameter" warnings
#ifndef J_UNUSED
#define J_UNUSED(x) (void)x;
#endif

#ifndef J_OUTOFLINE_TEMPLATE
#define J_OUTOFLINE_TEMPLATE inline
#endif
#ifndef J_INLINE_TEMPLATE
#define J_INLINE_TEMPLATE inline
#endif

//
#ifndef J_TRY
#define J_TRY try
#define J_CATCH(A) catch (A)
#define J_THROW(A) throw A
#define J_RETHROW throw
#endif

// - private pointer
template <typename T> static inline T *jGetPtrHelper(T *ptr) { return ptr; }
template <typename Wrapper> static inline typename Wrapper::pointer jGetPtrHelper(const Wrapper &p) { return p.data(); }

#undef J_DECLARE_PRIVATE
#define J_DECLARE_PRIVATE(Class) \
    Class##Private *d_ptr; \
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(jGetPtrHelper(d_ptr)); } \
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(jGetPtrHelper(d_ptr)); } \
    friend class Class##Private;

#undef J_DECLARE_PRIVATE_D
#define J_DECLARE_PRIVATE_D(Dptr, Class) \
    Class##Private *Dptr; \
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(Dptr); } \
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(Dptr); } \
    friend class Class##Private;

#undef J_DECLARE_PUBLIC
#define J_DECLARE_PUBLIC(Class) \
    Class * q_ptr; \
    inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
    inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
    friend class Class;

#undef J_D
#undef J_Q
#define J_D(Class) Class##Private * const d = d_func()
#define J_Q(Class) Class * const q = q_func()

typedef signed char jint8;
typedef unsigned char juint8;
typedef short jint16;
typedef unsigned short juint16;
typedef int jint32;
typedef unsigned int juint32;
typedef long long jint64;
typedef unsigned long long juint64;
typedef double jreal;

/*
  juintptr and jptrdiff is guaranteed to be the same size as a pointer, i.e.

      sizeof(void *) == sizeof(juintptr)
      && sizeof(void *) == sizeof(jptrdiff)
*/
template <int> struct JIntegerForSize;
template <>    struct JIntegerForSize<1> { typedef juint8  Unsigned; typedef jint8  Signed; };
template <>    struct JIntegerForSize<2> { typedef juint16 Unsigned; typedef jint16 Signed; };
template <>    struct JIntegerForSize<4> { typedef juint32 Unsigned; typedef jint32 Signed; };
template <>    struct JIntegerForSize<8> { typedef juint64 Unsigned; typedef jint64 Signed; };
template <class T> struct JIntegerForSizeof: JIntegerForSize<sizeof(T)> { };
typedef JIntegerForSizeof<void*>::Unsigned juintptr;
typedef JIntegerForSizeof<void*>::Signed jptrdiff;

// - class JFlag -

class JFlag
{
    int i;
public:
    inline JFlag(int i);
    inline operator int() const { return i; }
};

inline JFlag::JFlag(int ai) : i(ai) {}

// - class JIncompatibleFlag -

class JIncompatibleFlag
{
    int i;
public:
    inline explicit JIncompatibleFlag(int i);
    inline operator int() const { return i; }
};

inline JIncompatibleFlag::JIncompatibleFlag(int ai) : i(ai) {}

// - class JFlags -

template<typename Enum>
class JFlags
{
    typedef void **Zero;
    int i;
public:
    typedef Enum enum_type;
    inline JFlags(const JFlags &f) : i(f.i) {}
    inline JFlags(Enum f) : i(f) {}
    inline JFlags(Zero = 0) : i(0) {}
    inline JFlags(JFlag f) : i(f) {}

    inline JFlags &operator=(const JFlags &f) { i = f.i; return *this; }
    inline JFlags &operator&=(int mask) { i &= mask; return *this; }
    inline JFlags &operator&=(unsigned int mask) { i &= mask; return *this; }
    inline JFlags &operator|=(JFlags f) { i |= f.i; return *this; }
    inline JFlags &operator|=(Enum f) { i |= f; return *this; }
    inline JFlags &operator^=(JFlags f) { i ^= f.i; return *this; }
    inline JFlags &operator^=(Enum f) { i ^= f; return *this; }

     inline operator int() const { return i; }

    inline JFlags operator|(JFlags f) const { return JFlags(Enum(i | f.i)); }
    inline JFlags operator|(Enum f) const { return JFlags(Enum(i | f)); }
    inline JFlags operator^(JFlags f) const { return JFlags(Enum(i ^ f.i)); }
    inline JFlags operator^(Enum f) const { return JFlags(Enum(i ^ f)); }
    inline JFlags operator&(int mask) const { return JFlags(Enum(i & mask)); }
    inline JFlags operator&(unsigned int mask) const { return JFlags(Enum(i & mask)); }
    inline JFlags operator&(Enum f) const { return JFlags(Enum(i & f)); }
    inline JFlags operator~() const { return JFlags(Enum(~i)); }

    inline bool operator!() const { return !i; }

    inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == int(f) ); }
};

#define J_DECLARE_FLAGS(Flags, Enum) \
    typedef JFlags<Enum> Flags;

#define J_DECLARE_INCOMPATIBLE_FLAGS(Flags) \
inline JIncompatibleFlag operator|(Flags::enum_type f1, int f2) \
{ return JIncompatibleFlag(int(f1) | f2); }

#define J_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
inline JFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \
{ return JFlags<Flags::enum_type>(f1) | f2; } \
inline JFlags<Flags::enum_type> operator|(Flags::enum_type f1, JFlags<Flags::enum_type> f2) \
{ return f2 | f1; } J_DECLARE_INCOMPATIBLE_FLAGS(Flags)

/*
   Utility macros and inline functions
*/

template <typename T>
inline T jAbs(const T &t) { return t >= 0 ? t : -t; }

inline int jRound(jreal d)
{ return d >= jreal(0.0) ? int(d + jreal(0.5)) : int(d - int(d-1) + jreal(0.5)) + int(d-1); }

inline jint64 jRound64(jreal d)
{ return d >= jreal(0.0) ? jint64(d + jreal(0.5)) : jint64(d - jreal(jint64(d-1)) + jreal(0.5)) + jint64(d-1); }

template <typename T>
inline const T &jMin(const T &a, const T &b) { return (a < b) ? a : b; }
template <typename T>
inline const T &jMax(const T &a, const T &b) { return (a < b) ? b : a; }
template <typename T>
inline const T &jBound(const T &min, const T &val, const T &max)
{ return jMax(min, jMin(max, val)); }

template <typename T>
inline void jSwap(T &value1, T &value2)
{
#if 0
    std::swap(value1, value2);
#else
    T c(value1); value1=value2; value2=c;
#endif
}

// - class JBool -

class JBool
{
    bool b;

public:
    inline explicit JBool(bool B) : b(B) {}
    inline operator const void *() const
    { return b ? static_cast<const void *>(this) : static_cast<const void *>(0); }
};

inline bool operator==(JBool b1, bool b2) { return !b1 == !b2; }
inline bool operator==(bool b1, JBool b2) { return !b1 == !b2; }
inline bool operator==(JBool b1, JBool b2) { return !b1 == !b2; }
inline bool operator!=(JBool b1, bool b2) { return !b1 != !b2; }
inline bool operator!=(bool b1, JBool b2) { return !b1 != !b2; }
inline bool operator!=(JBool b1, JBool b2) { return !b1 != !b2; }

static inline bool jFuzzyCompare(double p1, double p2)
{
    return (jAbs(p1 - p2) <= 0.000000000001 * jMin(jAbs(p1), jAbs(p2)));
}

static inline bool jFuzzyCompare(float p1, float p2)
{
    return (jAbs(p1 - p2) <= 0.00001f * jMin(jAbs(p1), jAbs(p2)));
}

/*!
  \internal
*/
static inline bool jFuzzyIsNull(double d)
{
    return jAbs(d) <= 0.000000000001;
}

/*!
  \internal
*/
static inline bool jFuzzyIsNull(float f)
{
    return jAbs(f) <= 0.00001f;
}

/*
   This function tests a double for a null value. It doesn't
   check whether the actual value is 0 or close to 0, but whether
   it is binary 0.
*/
static inline bool jIsNull(double d)
{
    union U {
        double d;
        juint64 u;
    };
    U val;
    val.d = d;
    return val.u == juint64(0);
}

/*
   This function tests a float for a null value. It doesn't
   check whether the actual value is 0 or close to 0, but whether
   it is binary 0.
*/
static inline bool jIsNull(float f)
{
    union U {
        float f;
        juint32 u;
    };
    U val;
    val.f = f;
    return val.u == 0u;
}
/*
   JTypeInfo     - type trait functionality
   jIsDetached   - data sharing functionality
*/

/*
  The catch-all template.
*/

template <typename T> inline bool jIsDetached(T &) { return true; }

template <typename T>
class JTypeInfo
{
public:
    enum {
        isPointer = false,
        isComplex = true,
        isStatic = true,
        isLarge = (sizeof(T)>sizeof(void*)),
        isDummy = false
    };
};

//
template <typename T>
class JTypeInfo<T*>
{
public:
    enum {
        isPointer = true,
        isComplex = false,
        isStatic = false,
        isLarge = false,
        isDummy = false
    };
};

/*
   Specialize a specific type with:

     Q_DECLARE_TYPEINFO(type, flags);

   where 'type' is the name of the type to specialize and 'flags' is
   logically-OR'ed combination of the flags below.
*/
enum { /* TYPEINFO flags */
    J_COMPLEX_TYPE = 0,
    J_PRIMITIVE_TYPE = 0x1,
    J_STATIC_TYPE = 0,
    J_MOVABLE_TYPE = 0x2,
    J_DUMMY_TYPE = 0x4
};

#define J_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \
class JTypeInfo<TYPE > \
{ \
public: \
    enum { \
        isComplex = (((FLAGS) & J_PRIMITIVE_TYPE) == 0), \
        isStatic = (((FLAGS) & (J_MOVABLE_TYPE | J_PRIMITIVE_TYPE)) == 0), \
        isLarge = (sizeof(TYPE)>sizeof(void*)), \
        isPointer = false, \
        isDummy = (((FLAGS) & J_DUMMY_TYPE) != 0) \
    }; \
    static inline const char *name() { return #TYPE; } \
}

#define J_DECLARE_TYPEINFO(TYPE, FLAGS) \
template<> \
J_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)

/*
  JTypeInfo primitive specializations
*/
J_DECLARE_TYPEINFO(bool, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(char, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(signed char, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(unsigned char, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(short, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(unsigned short, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(int, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(unsigned int, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(long, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(unsigned long, J_PRIMITIVE_TYPE);
//J_DECLARE_TYPEINFO(__int64, J_PRIMITIVE_TYPE);
//J_DECLARE_TYPEINFO(unsigned __int64, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(float, J_PRIMITIVE_TYPE);
J_DECLARE_TYPEINFO(double, J_PRIMITIVE_TYPE);

/*
   These functions make it possible to use standard C++ functions with
   a similar name (especially template classes).
*/
JTHREADPOOL_EXPORT void *jMalloc(unsigned long size);
JTHREADPOOL_EXPORT void jFree(void *ptr);
JTHREADPOOL_EXPORT void *jRealloc(void *ptr, unsigned long size);
JTHREADPOOL_EXPORT void *jMallocAligned(unsigned long size, unsigned long alignment);
JTHREADPOOL_EXPORT void *jReallocAligned(void *ptr, unsigned long size, unsigned long oldsize, unsigned long alignment);
JTHREADPOOL_EXPORT void jFreeAligned(void *ptr);
JTHREADPOOL_EXPORT void *jMemCopy(void *dest, const void *src, unsigned long n);
JTHREADPOOL_EXPORT void *jMemSet(void *dest, int c, unsigned long n);

//
#define jstring std::string
#define jlist std::list
#define jvector std::vector
#define jmap std::map

// - class JThreadPoolCore -

class JThreadPoolCorePrivate;

class JTHREADPOOL_EXPORT JThreadPoolCore
{
public:
    static JThreadPoolCore *instance();
    static void releaseInstance();

    int run();
    int exec();

private:
    JThreadPoolCore();
    ~JThreadPoolCore();

private:
    JThreadPoolCorePrivate *d;
};

#endif // JTHREADPOOL_GLOBAL_H
